_zimfw_download_tarball() {
  if [[ ${URL} =~ <%= url_regex %> ]]; then
    readonly HOST=${match[3]}
    readonly REPO=${match[4]%.git}
  fi
  if [[ ${HOST} != github.com || -z ${REPO} ]]; then
    _zimfw_print_error "${URL} is not a valid URL. Will not try to ${ACTION}. The zimfw degit tool only supports GitHub URLs. Use zmodule option ${_zbold}--use git${_znormalred} to use git instead."
    return 1
  fi
  readonly HEADERS_TARGET=${DIR}/${TEMP}_headers
  {
    readonly INFO=("${(@f)"$(<${INFO_TARGET})"}")
    # Previous REV is in line 2, reserved for future use.
    readonly INFO_HEADER=${INFO[3]}
    readonly TARBALL_URL=https://api.github.com/repos/${REPO}/tarball/${REV}
    if [[ ${ACTION} == check ]]; then
      if [[ -z ${INFO_HEADER} ]] return 0
      if (( ${+commands[curl]} )); then
        command curl -IfsL -H ${INFO_HEADER} ${TARBALL_URL} >${HEADERS_TARGET}
      else
        command wget --spider -qS --header=${INFO_HEADER} ${TARBALL_URL} 2>${HEADERS_TARGET}
      fi
    else
      if (( ${+commands[curl]} )); then
        if ! ERR=$(command curl -fsSL ${INFO_HEADER:+-H} ${INFO_HEADER} -o ${TARBALL_TARGET} -D ${HEADERS_TARGET} ${TARBALL_URL} 2>&1); then
          _zimfw_print_error "Error downloading ${TARBALL_URL} with curl" ${ERR}
          return 1
        fi
      else
        # wget returns 8 when 304 Not Modified, so we cannot use wget's error codes
        command wget -qS ${INFO_HEADER:+--header=${INFO_HEADER}} -O ${TARBALL_TARGET} ${TARBALL_URL} 2>${HEADERS_TARGET}
      fi
    fi
    while IFS= read -r HEADER; do
      HEADER=${${HEADER## ##}%%$'\r'##}
      if [[ ${HEADER} == HTTP/* ]]; then
        HTTP_CODE=${${(s: :)HEADER}[2]}
      elif [[ ${${(L)HEADER%%:*}%% ##} == etag ]]; then
        ETAG=${${HEADER#*:}## ##}
      fi
    done < ${HEADERS_TARGET}
    if (( HTTP_CODE == 304 )); then
      # Not Modified
      command rm -f ${TARBALL_TARGET} 2>/dev/null
      return 0
    elif (( HTTP_CODE != 200 )); then
      _zimfw_print_error "Error downloading ${TARBALL_URL}, HTTP code ${HTTP_CODE}"
      return 1
    fi
    if [[ -z ${ETAG} ]]; then
      _zimfw_print_error "Error downloading ${TARBALL_URL}, no ETag header found in response"
      return 1
    fi
    if [[ ${ACTION} == check ]]; then
      command touch ${TARBALL_TARGET} # Update available
    else
      if ! print -lR "${URL}" "${REV}" "If-None-Match: ${ETAG}" >! ${INFO_TARGET} 2>/dev/null; then
        _zimfw_print_error "Error creating or updating ${INFO_TARGET}"
        return 1
      fi
    fi
  } always {
    command rm -f ${HEADERS_TARGET} 2>/dev/null
  }
}

_zimfw_untar_tarball() {
  if ! ERR=$(command tar -C ${1} -xzf ${TARBALL_TARGET} 2>&1); then
    _zimfw_print_error "Error extracting ${TARBALL_TARGET}" ${ERR}
    return 1
  fi
  local zsubdir
  for zsubdir in ${1}/*(/); do
    if ! ERR=$(command mv -f ${zsubdir}/*(DN) ${1} 2>&1 && command rmdir ${zsubdir} 2>&1); then
      _zimfw_print_error "Error moving ${zsubdir}" ${ERR}
      return 1
    fi
  done
}

_zimfw_tool_degit() {
  # This runs in a subshell
  readonly -i SUBMODULES=${6}
  readonly ACTION=${1} DIR=${2} URL=${3} REV=${5} ONPULL=${7} TEMP=.zdegit_${sysparams[pid]}_${RANDOM}
  readonly TARBALL_TARGET=${DIR}/${TEMP}_tarball.tar.gz INFO_TARGET=${DIR}/.zdegit
  case ${ACTION} in
    pre|prereinstall)
      local premsg
      if [[ ${ACTION} == pre ]] premsg=" Use zmodule option ${_zbold}-z${_znormalred}|${_zbold}--frozen${_znormalred} to disable this error or run ${_zbold}zimfw reinstall${_znormalred} to reinstall."
      if [[ -e ${DIR} ]]; then
        if [[ ! -r ${INFO_TARGET} ]]; then
          _zimfw_print_error $'Module was not installed using zimfw\'s degit.'${premsg}
          return 1
        fi
        readonly INFO=("${(@f)"$(<${INFO_TARGET})"}")
        if [[ ${URL} != ${INFO[1]} ]]; then
          _zimfw_print_error 'The zimfw degit URL does not match. Expected '${URL}.${premsg}
          return 1
        fi
      fi
      return 0
      ;;
    install)
      {
        _zimfw_create_dir ${DIR} && _zimfw_download_tarball && _zimfw_untar_tarball ${DIR} && _zimfw_pull_print_okay Installed || return 1
      } always {
        # return 1 does not change ${TRY_BLOCK_ERROR}, only changes ${?}
        (( TRY_BLOCK_ERROR = ? ))
        command rm -f ${TARBALL_TARGET} 2>/dev/null
        if (( TRY_BLOCK_ERROR )) command rm -rf ${DIR} 2>/dev/null
      }
      ;;
    check|update)
      readonly DIR_NEW=${DIR}${TEMP}
      {
        _zimfw_download_tarball || return 1
        if [[ ${ACTION} == check ]]; then
          if [[ -e ${TARBALL_TARGET} ]]; then
            _zimfw_print_okay 'Update available'
            return 4
          fi
          _zimfw_print_okay 'Already up to date' 1
          return 0
        else
          if [[ -e ${TARBALL_TARGET} ]]; then
            _zimfw_create_dir ${DIR_NEW} && _zimfw_untar_tarball ${DIR_NEW} || return 1
            if (( ${+commands[diff]} )); then
              LOG=$(command diff -x '.zdegit*' -x '*.zwc' -x '*.zwc.old' -qr ${DIR} ${DIR_NEW} 2>/dev/null)
              LOG=${${LOG//${DIR_NEW}/new}//${DIR}/old}
            fi
            if ! ERR=$({ command cp -f ${INFO_TARGET} ${DIR_NEW} && \
                command rm -rf ${DIR} && command mv -f ${DIR_NEW} ${DIR} } 2>&1); then
              _zimfw_print_error "Error updating ${DIR}" ${ERR}
              return 1
            fi
            _zimfw_pull_print_okay Updated 0 ${LOG} || return 1
          else
            _zimfw_pull_print_okay 'Already up to date' || return 1
          fi
        fi
      } always {
        command rm -f ${TARBALL_TARGET} 2>/dev/null
        command rm -rf ${DIR_NEW} 2>/dev/null
      }
      ;;
  esac
  # Check after successful install or update
  if [[ ${SUBMODULES} -ne 0 && -e ${DIR}/.gitmodules ]]; then
    _zimfw_print_warn "Module contains git submodules, which are not supported by zimfw's degit. Use zmodule option ${_zbold}--no-submodules${_znormalyellow} to disable this warning."
  fi
}
